package org.lex.jdbc.url.persist.xml;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.lex.jdbc.url.JdbcUrlTemplate;
import org.lex.jdbc.url.Variable;
import org.lex.jdbc.url.persist.AbstractJdbcTemplateDaoImpl;
import org.lex.jdbc.url.persist.IDriverDao;
import org.lex.jdbc.url.persist.IJdbcTemplateDao;

@SuppressWarnings("unchecked")
public class XmlJdbcTemplateDaoImpl extends AbstractJdbcTemplateDaoImpl
		implements IJdbcTemplateDao, XmlDaoConstants,
		XmlEntityDao<JdbcUrlTemplate> {

	private File templateConfigFile;
	private XmlDriverDaoImpl driverDao;
	private XmlDaoHelper<JdbcUrlTemplate> helper = new XmlDaoHelper<JdbcUrlTemplate>();

	public XmlJdbcTemplateDaoImpl(File parentDirectory) {
		String fileName = IDriverDao.class.getPackage().getName()
				+ ".drivers.xml";
		this.templateConfigFile = new File(parentDirectory, fileName);
		this.driverDao = new XmlDriverDaoImpl(parentDirectory);
	}

	// ================================
	// implements IJdbcTemplateDao
	// ================================

	@Override
	public List<JdbcUrlTemplate> getUserTemplates() throws IOException {
		return helper.getAllEntities(this.templateConfigFile, this);
	}

	@Override
	public void saveTemplate(JdbcUrlTemplate template) throws IOException {
		helper.save(this.templateConfigFile, this, template);
	}

	@Override
	public void updateTemplate(JdbcUrlTemplate oldTemplate,
			JdbcUrlTemplate newTemplate) throws IOException {
		this.helper.update(this.templateConfigFile, this, oldTemplate,
				newTemplate);
	}

	@Override
	public void deleteTemplate(JdbcUrlTemplate template) throws IOException {
		this.helper.delete(this.templateConfigFile, this, template);
	}

	// ================================
	// implements XmlEntityDao
	// ================================

	@Override
	public void marshal(JdbcUrlTemplate t, Element entityElement) {
		entityElement.addAttribute("driver", t.getDriver().getName());
		entityElement.addAttribute("name", t.getName());
		entityElement.addAttribute("template", t.getTemplate());
		entityElement.addAttribute("description", t.getDescription());
		for (Variable var : t.getVariables()) {
			Element varEle = entityElement.addElement("Variable");
			varEle.addAttribute("required", Boolean.toString(var.isRequired()));
			varEle.addAttribute("secret", Boolean.toString(var.isSecret()));
			varEle.addAttribute("name", var.getName());
			varEle.addAttribute("defaultValue", var.getDefaultValue());
			varEle.addAttribute("displayName", var.getDisplayName());
			varEle.addAttribute("description", var.getDescription());
		}
	}

	@Override
	public JdbcUrlTemplate unmarshal(Element entityElement) throws IOException {
		JdbcUrlTemplate t = new JdbcUrlTemplate();
		t.setDriver(this.driverDao.getDriverByName(entityElement
				.attributeValue("driver")));
		t.setName(entityElement.attributeValue("name"));
		t.setTemplate(entityElement.attributeValue("template"));
		t.setDescription(entityElement.attributeValue("description"));
		for (Iterator<Element> varEleIter = entityElement
				.elementIterator("Variable"); varEleIter.hasNext();) {
			Element varEle = varEleIter.next();
			Variable var = new Variable();
			var.setRequired(Boolean.parseBoolean(varEle
					.attributeValue("required")));
			var.setSecret(Boolean.parseBoolean(varEle.attributeValue("secret")));
			var.setName(varEle.attributeValue("name"));
			var.setDefaultValue(varEle.attributeValue("defaultValue"));
			var.setDisplayName(varEle.attributeValue("displayName"));
			var.setDescription(varEle.attributeValue("description"));
			t.getVariables().add(var);
		}
		return t;
	}

	@Override
	public Iterator<Element> getEntityIterator(Document doc) {
		return doc.getRootElement().elementIterator("Template");
	}

	@Override
	public Element createNewEntityElement(Document doc) {
		return doc.getRootElement().addElement("Template");
	}
}
